import {
  forwardRef,
  useEffect,
  useImperativeHandle,
  useRef,
  useState
} from 'react'
import CountUp from 'react-countup'

import top5NodataPng from '@/assets/icons/safeCoGovernance/top5Nodata.png'
import { uuid } from '@/utils/YunMaiUtils'

import type { Tb } from '../../../BigScreenBase/ModuleTitle'
import { ModuleTitle } from '../../../BigScreenBase/ModuleTitle'
import type { AssociationData } from '../../../BigScreenBase/interface'
import WordHScroll from '../../Components/WordHScroll'
import type { TenTypeWarnDataItem, Top5WarnDataItem } from '../../data'
import { getAlarmCarNum, getTenTypeWarnData, getTop5WarnData } from '../../data'
import useBgWarnScoket from '../../hooks/useBgWarnScoket'
import type { SwitchAndIntervalRef, WarDataType } from '../../interface'
import { getDuration } from '../../utils'
import TenTypeItem from '../Components/TenTypeItem'

import './index.less'

interface LeftWarnDataProps {
  selectedAssociationItem: AssociationData
  onClearTimer: () => void
  onStartTimer: () => void
}

//d:今日，q:季,m 月,y 年
const WARNTITLETAB: Tb[] = [
  { name: '今日', value: 'd' },
  { name: '本月', value: 'm' },
  { name: '本季', value: 'q' },
  { name: '本年', value: 'y' }
]

export interface TenTypeWarnDataItemRender extends TenTypeWarnDataItem {
  prevValue: number
  prevMaxValue: number
  id: string
}

const TENTYPEDEFAULTITEM: TenTypeWarnDataItemRender = {
  name: '',
  value: 0,
  piont: 0,
  prevValue: 0,
  prevMaxValue: 0,
  id: ''
}

const TENTYPEDEFAULTDATALIST: TenTypeWarnDataItemRender[] = Array(10).map(
  () => ({ ...TENTYPEDEFAULTITEM, id: uuid() })
)

interface Top5WarnDataItemRender extends Top5WarnDataItem {
  translateX?: 0 | -102
  duration?: 0 | 0.5
}

const LeftWarnData = forwardRef<SwitchAndIntervalRef, LeftWarnDataProps>(
  (props, ref) => {
    const {
      selectedAssociationItem: { key },
      onClearTimer,
      onStartTimer
    } = props
    const [warnDataType, setWarnDataType] = useState<WarDataType>('d')
    const warnDataTypeRef = useRef<WarDataType>('d')
    const warnDataTypeIntervalRef = useRef<any>()

    //报警总数，数字翻牌器
    const [allWarnSum, setAllWarnSum] = useState<number>(0) //http接口获取的报警总数
    const [prevWarnSum, setPrevWarnSum] = useState<number>(0)
    const prevWarnSumRef = useRef<number>(0)
    const [endWarnSum, setEndWarnSum] = useState<number>(0)
    const endWarnSumRef = useRef<number>(0)

    const [top5WarnDataList, setTop5WarnDataList] = useState<
      Top5WarnDataItemRender[]
    >([])
    const top5WarnDataListRef = useRef<Top5WarnDataItemRender[]>([])
    const [hasTop5WarnDataLoaded, setHasTop5WarnDataLoaded] =
      useState<boolean>(false)

    //车辆报警总数
    const [carWarnSum, setCarWarnSum] = useState<number>(0)
    const [pevCarWarnSum, setPevCarWarnSum] = useState<number>(0)
    const prevCarWarnSumRef = useRef<number>(0)
    const [endCarWarnSum, setEndCarWarnSum] = useState<number>(0)
    const endCarWarnSumRef = useRef<number>(0)
    const carWarnSumReqIntervalIdRef = useRef<any>() //每隔10s请求一次接口

    const [tenTypeWarnDataList, setTenTypeWarnDataList] = useState<
      TenTypeWarnDataItemRender[]
    >(TENTYPEDEFAULTDATALIST)
    const [tenTypeMaxValue, setTenTypeMaxValue] = useState<number>(0)

    //---top5  scoket--
    const { bgWarnSocketData, clearWebScoket, connectWebSocket } =
      useBgWarnScoket({ entId: key })
    const top5SocketDataListRef = useRef<Top5WarnDataItem[]>([])
    const top5SocketDatatRunInterInRef = useRef<any>() //每隔3秒跑一条top5SocketDataListRef.current
    const top5ItemTranslateXTIdRef = useRef<any>() //500ms后执行 过渡状态2动画
    const top5DelLastItemTIdRef = useRef<any>() //500ms后 尾端删除

    useEffect(() => {
      if (!bgWarnSocketData || !Object.keys(bgWarnSocketData).length) return
      top5SocketDataListRef.current.push(bgWarnSocketData)
    }, [bgWarnSocketData])

    //每隔3秒跑一条socket数据
    function _runTop5SocketDataList() {
      top5SocketDatatRunInterInRef.current = setInterval(() => {
        if (!top5SocketDataListRef.current.length) return
        const firstTop5WarnData = top5SocketDataListRef.current.shift() //首端删除
        if (!firstTop5WarnData) return
        if (top5ItemTranslateXTIdRef.current) {
          clearTimeout(top5ItemTranslateXTIdRef.current)
        }
        if (top5DelLastItemTIdRef.current) {
          clearTimeout(top5DelLastItemTIdRef.current)
        }
        // console.log('--LeftWarData--bgWarnSocketData---:', bgWarnSocketData)
        const isExist =
          top5WarnDataListRef.current.findIndex(
            (prevDataItem) =>
              prevDataItem.alarmGUID === firstTop5WarnData.alarmGUID
          ) > -1
            ? true
            : false
        if (isExist) {
          //没有产生新的报警
          top5WarnDataListRef.current = top5WarnDataListRef.current.map(
            (prevDataItem) => ({
              //  更新alerDateText相对于day()当前时间
              ...prevDataItem,
              translateX: 0,
              duration: 0,
              alerDateText: getDuration(prevDataItem.alermDate)
            })
          )
          setTop5WarnDataList(top5WarnDataListRef.current)
        } else {
          //allSum
          prevWarnSumRef.current = endWarnSumRef.current
          setPrevWarnSum(prevWarnSumRef.current)

          let tempDataList = top5WarnDataListRef.current
          tempDataList.unshift(firstTop5WarnData) // 6个
          //过渡状态1
          tempDataList = tempDataList.map((prevDataItem) => ({
            ...prevDataItem,
            alerDateText: getDuration(prevDataItem.alermDate),
            translateX: -102,
            duration: 0
          }))
          setTop5WarnDataList(tempDataList)
          //过渡状态2动画
          top5ItemTranslateXTIdRef.current = setTimeout(() => {
            tempDataList = tempDataList.map((prevDataItem) => ({
              ...prevDataItem,
              translateX: 0,
              duration: 0.5
            }))
            setTop5WarnDataList(tempDataList)
            top5WarnDataListRef.current = tempDataList
            endWarnSumRef.current += 1
            setEndWarnSum(endWarnSumRef.current)
            if (top5WarnDataListRef.current.length > 5) {
              //尾端删除
              top5DelLastItemTIdRef.current = setTimeout(() => {
                tempDataList.pop()
                setTop5WarnDataList(tempDataList)
                top5WarnDataListRef.current = tempDataList
              }, 500)
            }
          }, 500)
        }
      }, 3000)
    }

    function _resetTop5WarData() {
      setTop5WarnDataList([])
      setAllWarnSum(0)
      prevWarnSumRef.current = 0
      setPrevWarnSum(0)
      endWarnSumRef.current = 0
      setEndWarnSum(0)
    }

    //top5
    function _getTop5WarnDataFn(entIdParam: string, timeType: WarDataType) {
      top5SocketDataListRef.current = [] //只要请求接口，就要重置为[],每隔3s没来得及展示的报警，就不要展示了，因为 endWarnSumRef.current = allSum已经是最新数据了，而每隔3sendWarnSumRef.current  += 1会滞后，会在最新endWarnSumRef上继续添加，导致数据对不上
      return getTop5WarnData({ entId: entIdParam, timeType, topNum: 5 })
        .then((res) => {
          const {
            data: { allSum, alermTopList }
          } = res
          // console.log('--getTop5WarnData--res--:', res);
          const newAlermTopList = alermTopList.map((listItem) => ({
            ...listItem,
            alerDateText: getDuration(listItem.alermDate)
          }))
          setTop5WarnDataList(newAlermTopList)
          top5WarnDataListRef.current = newAlermTopList
          setAllWarnSum(allSum)
          prevWarnSumRef.current = endWarnSumRef.current
          setPrevWarnSum(prevWarnSumRef.current)
          endWarnSumRef.current = allSum
          setEndWarnSum(endWarnSumRef.current)
        })
        .catch((err) => {
          _resetTop5WarData()
          setHasTop5WarnDataLoaded(true)
          console.error('--LeftWarnData--getTop5WarnData--err--:', err)
        })
    }

    //车辆报警总数
    function _resetAlarmCarNum() {
      setCarWarnSum(0)
      prevCarWarnSumRef.current = 0
      setPevCarWarnSum(0)
      endCarWarnSumRef.current = 0
      setEndCarWarnSum(0)
    }

    function _getAlarmCarNumFn(entIdParam: string, timeType: WarDataType) {
      if (carWarnSumReqIntervalIdRef.current) {
        clearInterval(carWarnSumReqIntervalIdRef.current)
      }
      getAlarmCarNum({ entId: entIdParam, timeType })
        .then((res) => {
          const {
            data: { carSum }
          } = res
          const finalCarSum = carSum ?? 0
          setCarWarnSum(finalCarSum)
          prevCarWarnSumRef.current = endCarWarnSumRef.current
          setPevCarWarnSum(prevCarWarnSumRef.current)
          endCarWarnSumRef.current = finalCarSum
          setEndCarWarnSum(finalCarSum)
          //每隔十秒请求一次
          carWarnSumReqIntervalIdRef.current = setInterval(() => {
            _getAlarmCarNumFn(entIdParam, timeType)
          }, 10000)
        })
        .catch((err) => {
          console.error('--LeftWarnData--err--:', err)
          if (carWarnSumReqIntervalIdRef.current) {
            clearInterval(carWarnSumReqIntervalIdRef.current)
          }
          _resetAlarmCarNum()
        })
    }

    //10种类型
    function _getTenTypeWarnDataFn(
      type: 'inital' | 'switchAssociation' | 'tabChange',
      entIdParam: string,
      warnDataTypeParam: WarDataType
    ) {
      return getTenTypeWarnData({
        entId: entIdParam,
        timeType: warnDataTypeParam
      })
        .then((res) => {
          const {
            data: { alermKvs = [] }
          } = res
          const prevMaxValue = tenTypeMaxValue
          const tempTenTypeMaxValue = alermKvs[0] ? alermKvs[0].value : 0
          setTenTypeMaxValue(tempTenTypeMaxValue)
          const validTenTypeWarnDataList = tenTypeWarnDataList.filter(
            (listItem) => listItem.name
          )
          const newAlermKvs: TenTypeWarnDataItemRender[] = alermKvs.map(
            (alerItem) => {
              const prevAlerDetail = validTenTypeWarnDataList.find(
                (prevAlerItem) => prevAlerItem.name === alerItem.name
              )
              const prevValue = prevAlerDetail ? prevAlerDetail.value : 0
              return {
                ...alerItem,
                prevValue,
                prevMaxValue,
                id: uuid()
              }
            }
          )
          if (newAlermKvs.length < 10) {
            for (let i = newAlermKvs.length; i < 10; i++) {
              newAlermKvs.push({ ...TENTYPEDEFAULTITEM, id: uuid() })
            }
          }
          // console.log('--newAlermKvs--:', newAlermKvs);
          setTenTypeWarnDataList(newAlermKvs)
        })
        .catch((err) => {
          clearWarnDataInterval()
          setTenTypeWarnDataList([])
          console.error('--LeftWarnData--getTenTypeWarnData--err--:', err)
        })
    }

    useImperativeHandle(ref, () => ({
      switchAssociation: (newAssociationId) => {
        if (top5SocketDatatRunInterInRef.current) {
          clearInterval(top5SocketDatatRunInterInRef.current)
        }
        if (top5ItemTranslateXTIdRef.current) {
          clearTimeout(top5ItemTranslateXTIdRef.current)
        }
        if (top5DelLastItemTIdRef.current) {
          clearTimeout(top5DelLastItemTIdRef.current)
        }

        clearWarnDataInterval()
        clearWebScoket()
        _getTenTypeWarnDataFn(
          'switchAssociation',
          newAssociationId,
          warnDataType
        ).then(() => {
          startWarnDataInterval()
        })

        _resetTop5WarData()
        setHasTop5WarnDataLoaded(false)
        _getTop5WarnDataFn(newAssociationId, warnDataTypeRef.current).then(
          () => {
            connectWebSocket()
            _runTop5SocketDataList()
            setHasTop5WarnDataLoaded(true)
          }
        )

        _resetAlarmCarNum()
        _getAlarmCarNumFn(newAssociationId, warnDataTypeRef.current)
      },
      intervalRefresh: () => {}
    }))

    useEffect(() => {
      setHasTop5WarnDataLoaded(false)
      _getTop5WarnDataFn(key, 'd').then(() => {
        connectWebSocket()
        _runTop5SocketDataList()
        setHasTop5WarnDataLoaded(true)
      })
      _getAlarmCarNumFn(key, 'd')
      _getTenTypeWarnDataFn('inital', key, 'd').then(() => {
        startWarnDataInterval()
      })
      return () => {
        clearWebScoket()
        clearWarnDataInterval()
        if (top5SocketDatatRunInterInRef.current) {
          clearInterval(top5SocketDatatRunInterInRef.current)
        }
        if (top5ItemTranslateXTIdRef.current) {
          clearTimeout(top5ItemTranslateXTIdRef.current)
        }
        if (top5DelLastItemTIdRef.current) {
          clearTimeout(top5DelLastItemTIdRef.current)
        }
        if (carWarnSumReqIntervalIdRef.current) {
          clearInterval(carWarnSumReqIntervalIdRef.current)
        }
      }
    }, [])

    //切换 "d" | "m" | "q" | "y"
    const handleTabChange = (activeTab: Tb) => {
      const currType = activeTab.value as WarDataType
      if (currType === warnDataType || !hasTop5WarnDataLoaded) return //!hasTop5WarnDataLoaded 接口在请求时是不允许点击的
      onClearTimer()
      clearWebScoket()
      setWarnDataType(currType)
      warnDataTypeRef.current = currType

      if (top5SocketDatatRunInterInRef.current) {
        clearInterval(top5SocketDatatRunInterInRef.current)
      }
      if (top5ItemTranslateXTIdRef.current) {
        clearTimeout(top5ItemTranslateXTIdRef.current)
      }
      if (top5DelLastItemTIdRef.current) {
        clearTimeout(top5DelLastItemTIdRef.current)
      }
      _getTop5WarnDataFn(key, currType).then(() => {
        connectWebSocket()
        _runTop5SocketDataList()
      })

      _getAlarmCarNumFn(key, currType)

      _getTenTypeWarnDataFn('tabChange', key, currType).then(() => {
        startWarnDataInterval()
        onStartTimer()
      })
    }

    function clearWarnDataInterval() {
      if (warnDataTypeIntervalRef.current) {
        clearInterval(warnDataTypeIntervalRef.current)
        warnDataTypeIntervalRef.current = undefined
      }
    }

    //风险数据tyep10、top5自动切换
    function startWarnDataInterval() {
      clearWarnDataInterval()
      warnDataTypeIntervalRef.current = setInterval(() => {
        const currTypeIndex = WARNTITLETAB.findIndex(
          (listItem) => listItem.value === warnDataTypeRef.current
        )
        let nextTypeIndex = 0
        if (currTypeIndex >= WARNTITLETAB.length - 1) {
          nextTypeIndex = 0
        } else {
          nextTypeIndex = currTypeIndex + 1
        }

        const currTypeItem = WARNTITLETAB[nextTypeIndex]
        if (!currTypeItem) {
          throw new Error('实施风险数据自动切换，为找当当前项')
        }
        const currWarnDataType = currTypeItem.value as WarDataType
        setWarnDataType(currWarnDataType)
        warnDataTypeRef.current = currWarnDataType

        if (top5SocketDatatRunInterInRef.current) {
          clearInterval(top5SocketDatatRunInterInRef.current)
        }
        if (top5ItemTranslateXTIdRef.current) {
          clearTimeout(top5ItemTranslateXTIdRef.current)
        }
        if (top5DelLastItemTIdRef.current) {
          clearTimeout(top5DelLastItemTIdRef.current)
        }
        clearWebScoket()
        _getTop5WarnDataFn(key, warnDataTypeRef.current).then(() => {
          connectWebSocket()
          _runTop5SocketDataList()
        })

        _getAlarmCarNumFn(key, warnDataTypeRef.current)

        _getTenTypeWarnDataFn('tabChange', key, warnDataTypeRef.current)
      }, 60000)
    }

    return (
      <div className="bigscreen-module ms-module" style={{ height: '723px' }}>
        <ModuleTitle
          title={'实时风险数据'}
          activeKey={warnDataType}
          tab={WARNTITLETAB}
          tabChange={handleTabChange}
          onTitleTabMouseEnter={clearWarnDataInterval}
          onTitleTabMouseLeave={startWarnDataInterval}
        ></ModuleTitle>
        <div className="left-warn-data-container">
          <div className="container-warn-count">
            <div className="dr_count_item">
              <div className="dr_count_num">
                <CountUp start={prevWarnSum} end={endWarnSum} duration={1} />
              </div>
              <div className="dr_label">风险报警总数</div>
            </div>
            <div className="dr_count_item">
              <div className="dr_count_num">
                <CountUp
                  start={pevCarWarnSum}
                  end={endCarWarnSum}
                  duration={1}
                />
              </div>
              <div className="dr_label">车辆报警总数</div>
            </div>
          </div>

          <div className="container-warn-top5">
            {hasTop5WarnDataLoaded && !top5WarnDataList.length ? (
              <div className="top5-nodata">
                <img src={top5NodataPng} alt="暂无数据" />
                <p>暂无实时风险数据</p>
              </div>
            ) : (
              <div className="top5-data-list">
                {top5WarnDataList.map((dataItem, dataIndex) => (
                  <div
                    className="list-item"
                    key={dataItem.alarmGUID}
                    style={{
                      transition: `transform ${dataItem.duration ?? 0}s ease`,
                      transform: `translateX(${dataItem.translateX ?? 0}px)`
                    }}
                  >
                    <div className="item-top">
                      <p className="item-aler-aler-time">
                        {dataItem.alerDateText}
                      </p>
                      <div className="item-aler-name">
                        <WordHScroll>
                          <span>{dataItem.alermName}</span>
                        </WordHScroll>
                      </div>
                    </div>
                    <div className="item-bottom">
                      <p className="item-aler-personname">
                        {dataItem.personName}
                      </p>
                      <p className="item-aler-platenumber">
                        {dataItem.carBrand}
                      </p>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
          <div className="line-radius" style={{ margin: '16px 0' }}></div>
          <div className="container-10type">
            {tenTypeWarnDataList.map((alerData, alerIndex) => (
              <TenTypeItem
                key={alerData.id}
                alerData={alerData}
                alerIndex={alerIndex}
                tenTypeMaxValue={!alerData.name ? 0 : tenTypeMaxValue}
              />
            ))}
          </div>
        </div>
      </div>
    )
  }
)

export default LeftWarnData
